package se.citerus.dddsample.domain.model.cargo;

import org.apache.commons.lang.Validate;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import se.citerus.dddsample.domain.model.location.Location;
import se.citerus.dddsample.domain.shared.AbstractSpecification;
import se.citerus.dddsample.domain.shared.ValueObject;

import java.util.Date;

/**
 * 运送规格：定义了运送目标 <b>Route specification.</b> Describes where a cargo orign and
 * destination is, and the arrival deadline.
 */
public class RouteSpecification extends AbstractSpecification<Itinerary> implements ValueObject<RouteSpecification> {

	private static final long serialVersionUID = 1L;

	private Location origin;
	private Location destination;// 目的地
	private Date arrivalDeadline;// 到达日期

	/**
	 * @param origin origin location - can't be the same as the destination
	 * @param destination destination location - can't be the same as the origin
	 * @param arrivalDeadline arrival deadline
	 */
	public RouteSpecification(final Location origin, final Location destination, final Date arrivalDeadline) {
		Validate.notNull(origin, "Origin is required");
		Validate.notNull(destination, "Destination is required");
		Validate.notNull(arrivalDeadline, "Arrival deadline is required");
		Validate.isTrue(!origin.sameIdentityAs(destination), "Origin and destination can't be the same: " + origin);

		this.origin = origin;
		this.destination = destination;
		this.arrivalDeadline = (Date) arrivalDeadline.clone();
	}

	/**
	 * @return Specified origin location.
	 */
	public Location origin() {
		return origin;
	}

	/**
	 * @return Specfied destination location.
	 */
	public Location destination() {
		return destination;
	}

	/**
	 * @return Arrival deadline.
	 */
	public Date arrivalDeadline() {
		return new Date(arrivalDeadline.getTime());
	}

	@Override
	public boolean isSatisfiedBy(final Itinerary itinerary) {
		if (itinerary == null) {
			return false;
		}
		// 出发地要相同
		if(!origin().sameIdentityAs(itinerary.initialDepartureLocation())) {
			return false;
		}
		// 目的地要相同
		if(!destination().sameIdentityAs(itinerary.finalArrivalLocation())) {
			return false;
		}
		// 航线的到达时间要比配送要求的到达时间早
		if(!arrivalDeadline().after(itinerary.finalArrivalDate())) {
			return false;
		}
 		return true;
	}

	@Override
	public boolean sameValueAs(final RouteSpecification other) {
		return other != null
				&& new EqualsBuilder().append(this.origin, other.origin).append(this.destination, other.destination)
						.append(this.arrivalDeadline, other.arrivalDeadline).isEquals();
	}

	@Override
	public boolean equals(final Object o) {
		if (this == o)
			return true;
		if (o == null || getClass() != o.getClass())
			return false;

		final RouteSpecification that = (RouteSpecification) o;

		return sameValueAs(that);
	}

	@Override
	public int hashCode() {
		return new HashCodeBuilder().append(this.origin).append(this.destination).append(this.arrivalDeadline).toHashCode();
	}

	RouteSpecification() {
		// Needed by Hibernate
	}

}
